<?php
header('Content-type: text/plain');

require_once('frontstart.inc.php');   # defines: $options[], $context

class Application {
    function handle_request ($options) {
        global $options, $context;
        try {
            
            $op   = isset($_REQUEST['op']) ? $_REQUEST['op'] : 'getTree';
            $neat = (isset($_REQUEST['neat']) && $_REQUEST['neat']) ? 1 : 0;
            $results = Array( 'success'=>true );
            
            if ($op === 'getTree'){
                $dirsToScan = Array($options['user_document_root']);
                $tree       = Array();
                                
                // be sure that the user documents folder exists
                if ( !is_dir($options['user_document_root'])) {
                    if ( !mkdir($options['user_document_root'],0777,TRUE)) {
                        throw new \Exception('ERROR: cannot find or create directory for user documents');
                    }
                    echo "[]\n";
                    return(null);
                }
				
				//$export_dir = preg_replace("/\/\//","/",$options['user_document_root'] . "/" . $options['export_dir_name']);
                //if ( !is_dir($export_dir)) 
                //    if ( !mkdir($export_dir ,0777,TRUE)) 
                //        throw new \Exception('ERROR: cannot find or create directory for user exports');
                    
                while (count($dirsToScan) > 0) {
                    
                    $currDirString = array_shift($dirsToScan); 
                    $currDirItems  = Array(); // all dirs and files for the curr dir
                    $currDirFiles  = Array(); // all files for current dir
                    
                    foreach (new DirectoryIterator($currDirString) as $fileInfo) {
                        if ( preg_match("/^\./",$fileInfo->getFilename())) continue; // skip dots
                        
                        $path     = $fileInfo->getPath();
                        $filename = $fileInfo->getFilename();
                        $id       = substr("{$path}/{$filename}", strlen($options['user_document_root']) + 1, strlen("{$path}/{$filename}"));
                        
                        // make note of directories so we can scan later
                        if ( $fileInfo->isDir() ) {
                            $currDirItems[] = Array( 'id'=>$id, 'text'=>$fileInfo->getFilename(), 'expanded'=>false);
                            array_push($dirsToScan, "{$path}/{$filename}");
                        }
                        else {
                            // keep files in a seperate list so we can add them to the list after the folders
                            $currDirFiles[] = ARRAY('id'=>$id, 'text'=>$fileInfo->getFilename(), 'leaf'=>true);
                        }
                    }
                    
                    foreach($currDirFiles as $file)
                        $currDirItems[] = $file;
                    
                    //////////////////////////////////////
                    // add all current dir items to tree
                    //////////////////////////////////////
                    $currTreeLocn = &$tree;
                    
                    // if we are not currently at the root then navigate to the correct array locn 
                    if ($currDirString !== $options['user_document_root']){
                        $currDirString = substr($currDirString,strlen($options['user_document_root']) + 1,strlen($currDirString));
                        
                        foreach( preg_split("/\//", $currDirString) as $dir )
                        {
                            for ($i = 0; $i < count($currTreeLocn) ; $i++){
                                if (!isset($currTreeLocn[$i]['leaf']) && ($currTreeLocn[$i]['text'] === $dir)){
                                    // traverse to next directory down
                                    if (isset($currTreeLocn[$i]['children'])){
                                        $currTreeLocn = &$currTreeLocn[$i]['children'];
                                    }    
                                    // if there is no child dir set we must be at the end of the branch
                                    else{
                                        $currTreeLocn[$i]['children'] = $currDirItems;
                                        break;
                                    }
                                }
                            } // for ($i = 0; $i < count($currTreeLocn) ; $i++){}
                        } // foreach( preg_split("/\//", $currDirString) as $dir )
                    } // if were not at the root dir
                    else {
                        $currTreeLocn = $currDirItems;
                    }
                } // while more dirs to scan
                
                $results['id'] = 'src';
                $results['text'] = 'files';
                $results['children'] = $tree;
            } // op === getTree
            else if ( $op === 'move' ) {
                if (! isset($_REQUEST['from']) || strlen($_REQUEST['from']) === 0) throw new \Exception("ERROR: Source URL must be supplied");
                if (! isset($_REQUEST['to']) || strlen($_REQUEST['to']) === 0) throw new \Exception("ERROR: Destination URL must be supplied");
                if (preg_match("/\.\./",$_REQUEST['to'])) throw new \Exception("Invalid url name");
				if (preg_match("/\.\./",$_REQUEST['from'])) throw new \Exception("Invalid url name");
				if (! file_exists($options['user_document_root'] . "/" . $_REQUEST['from'])) throw new \Exception("ERROR: Source file does not exist");
                
                $from_dir = preg_replace("/\/\//", "/", $options['user_document_root'] . "/" . $_REQUEST['from']);
                $is_dir   = is_dir($from_dir);
				preg_match("/\/[^\/]+[\/]{0,}$/",$from_dir, $dir_name);
                $to_dir   = preg_replace("/\/\//", "/", $options['user_document_root'] . "/" . $_REQUEST['to'] . "/" . $dir_name[0] );
                
                if ( is_file($to_dir) || is_dir($to_dir) )
                    throw new \Exception("ERROR: Destination folder already exists");

                if (rename($from_dir,$to_dir) === false)
                    throw new \Exception("Unable to move directory");
                
            } 
			else if (  $op === 'rename' ){
				// from is complete url
                // to is just new dir/file name
                if (! isset($_REQUEST['from']) || strlen($_REQUEST['from']) === 0) throw new \Exception("ERROR: Source URL must be supplied");
                if (! isset($_REQUEST['to']) || strlen($_REQUEST['to']) === 0) throw new \Exception("ERROR: Destination URL must be supplied");
                if (! file_exists($options['user_document_root'] . "/" . $_REQUEST['from'])) throw new \Exception("ERROR: Source file does not exist");
                
                $from_dir = preg_replace("/\/\//", "/", $options['user_document_root'] . "/" . $_REQUEST['from']);
				$to_dir   = preg_replace("/\/\//", "/", preg_replace("/\/[^\/]+[\/]{0,1}$/","",$from_dir) . "/{$_REQUEST['to']}");
				   
                if ( is_file($to_dir) || is_dir($to_dir) )
                    throw new \Exception("ERROR: Destination folder already exists");
                 
                if (rename($from_dir,$to_dir) === false)
                    throw new \Exception("Unable to move directory");
			}
            else if ( $op === 'mkdir' ){
                if (! isset($_REQUEST['dir_path']) || strlen($_REQUEST['dir_path'] === 0)) throw new \Exception("ERROR: New directory path must be supplied");
                if (! isset($_REQUEST['dir_name']) || strlen($_REQUEST['dir_name'] === 0)) throw new \Exception("ERROR: New directory name must be supplied");
                if (preg_match("/\.\./",$_REQUEST['dir_name'])) throw new \Exception("Invalid Directory Name");
				if (preg_match("/\.\./",$_REQUEST['dir_path'])) throw new \Exception("Invalid Directory Path");
				
                $newDir = $options['user_document_root'] . "/" . $_REQUEST['dir_path'];
                $newDir = preg_replace("/\/\//",'/',$newDir);
                
                if ( ! is_dir($newDir) ) {
                    if ( is_file($newDir) )
                        $newDir = preg_replace("/\/[^\/]+[\/]{0,1}$/","",$newDir); // remove last element off of path if it is not a directory
                    else
                        throw new \Exception("Cannot find resource");
                }
                else {
                    $results['isDir'] = true;
                }
                $newDir .= (preg_match('/\/$/', $newDir) > 0 ? "" : "/") . $_REQUEST['dir_name'];
                
                if (mkdir($newDir, 0777, true) === false)
                    throw new \Exception("Unable to create directory");
            }
            else if ( $op === 'delete' || $op == 'rmdir' || $op == 'unlink' ){
                if (! isset($_REQUEST['dir_path']) || strlen($_REQUEST['dir_path'] === 0)) throw new \Exception("ERROR: Directory path must be supplied");
                
                $dir = preg_replace("/\/\//", "/", $options['user_document_root'] . '/' . $_REQUEST['dir_path']);

                if (is_dir($dir) === true){
                	if ( count( scandir($dir) ) > 0)
                        if ( isset($_REQUEST['force']) && $_REQUEST['force'] == 1) {
                            $path = $dir;
                            //while dir has more than "." and ".." listed and were not in the target dir, empty sub dirs
                            while( count(scandir($path)) != 2 || ($path !== $dir) ) {
                                foreach( scandir($path) as $item ){
                                    if ( $item == '.' || $item == '..' )
                                        continue;
                                    
                                    $item = "{$path}/{$item}";
                                    
                                    if (is_file($item) === true){
                                        if (unlink($item) === false)
                                            throw new \Exception("ERROR: could not remove file [{$item}]");
                                    }
                                    else if (count(scandir($item)) > 2){
                                        $path = $item;
                                        break;
                                    }
                                    else if (rmdir($item) === false)
                                        throw new \Exception("ERROR: could not empty directory");
                                    
                                    // if dir is empty move up one dir
                                    if (count(scandir($path)) == 2 && $path != $dir)
                                        $path = preg_replace("/\/[^\/]+[\/]{0,1}$/","",$path);
                                }
                            }
                        }
                        else 
                            throw new \Exception("Directory is not empty");
                            
                    if (rmdir($dir) === false)
                        throw new \Exception("Unable to remove directory");
                }
                else if( is_file($dir) === true){
                	if (unlink($dir) == false)
                    	throw new \Exception("Unable to remove file [{$dir}]");
				}
                else 
                    throw new \Exception("Resource does not exist [{$dir}]");
            }
            else {
                $results['success'] = false;
                $results['msg'] = "Cannot perform operation";
            }
            
            $json = json_encode($results);
            
            if ($neat) {
                $json = preg_replace('/\\},\\{/', "},\n {", $json);
                $json = preg_replace('/\\],\\[/', "],\n [", $json);
                $json = preg_replace('/\\[\\{/', "[\n {", $json);
                $json = preg_replace('/\\}\\]/', "}\n ]", $json);
            }
            
            echo "{$json}\n";
        }
        catch (Exception $e) {
            $this->return_json_error($e->getMessage());
        }
        return(null);
    }

    function return_json_error ($message) {
        if (preg_match("/\n/",$message)) {
            $message = preg_replace("/ *\n */"," ",$message);
        }
        if (preg_match("/\\'/",$message)) {
            $message = preg_replace("/\\'/","\\'",$message);
        }
        echo "{\n";
        echo "    'success': false,\n";
        echo "    'msg': '$message'\n";
        echo "}\n";
    }
}

$application = new Application();
$application->handle_request($options);

